#pragma once

#include <wx/panel.h>
#include <wx/bitmap.h>
#include <wx/timer.h>
#include <vector>
#include <memory>

const int TILESIZE = 25;

struct Point {
    Point() = default;
    Point(const wxPoint &p) {
        x = p.x/TILESIZE;
        y = p.y/TILESIZE;
    }
    Point(int x, int y):x(x),y(y) {}
    int x;
    int y;
};

const Point border[] = {{-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1}};

enum VIEW {BLANK=-4, FLAG, OPEN};
enum MODEL {BOMB=-2, MINE, NUM};

struct Tile {
    int outer = BLANK;
    int inner = 0;
};

struct Stats {
    int flag = 0;
    int blank= 0;
};

#define FOREACH(pt, ele) for (int X = 0; X < PTR->Col; ++X)\
    for (int Y = 0; Y < PTR->Row; ++Y)\
        if (Point pt={X,Y} ;true)\
        if (Tile &ele = PTR->at(pt); true)

#define AROUND(pt,pt1,ele) for (const auto &pt0 : border)\
    if (Point pt1={pt0.x+(pt).x, pt0.y+(pt).y} ; PTR->valid(pt1))\
    if (Tile &ele = PTR->at(pt1); true)

class Board : public wxPanel {
  public:
    Board(wxWindow *parent, wxWindowID winid, const wxPoint& pos
          , const wxSize& size, long style, const wxString& name);

    void OnPaint(wxPaintEvent &event);
    void OnTimer(wxTimerEvent &event);
    void drawTile(const Point &pt, int idx);
    static const int timerId;

    void resize(size_t row, size_t col);
    size_t size() const;
    Tile& at(const Point &pt);
    void initMine(int mine_num,const Point &pt);
    bool valid(const Point &pt) const;
    Stats Count(const Point &pt);

    size_t Col;
    size_t Row;
    std::vector<Point> wrong_mine;
  private:
    std::unique_ptr<wxBitmap[]> ptr;
    const wxBitmap * tile;

    size_t toIndex(const Point &pt) const;
    Point toPoint(size_t idx) const;
    std::vector<Tile> pool;

    DECLARE_EVENT_TABLE()
};
